// <copyright file="DebugBuffer.cs" company="TenneySoftware">
// Copyright (c) 2009 All Right Reserved
// </copyright>
// <author>Robert Tenney</author>
// <email>rob10e@yahoo.com</email>
// <date>April 2009</date>
// <summary>The debug buffer holds the data that is needed by the debug console for messages to display on screen.</summary>

// License:

// Product: RPGRoguelikeEngine .Net
// Author: Robert N. Tenney
// Copyright: June 2009

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation version 2
// of the License.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

// This license covers all source code, binaries, and other materials related to this project
// unless specifically stated otherwise.

using System;
using System.Collections.Generic;

namespace TenneySoftware.Engine.Debug {
    /// <summary>
    /// The debug buffer holds the data that is needed by the debug console for messages to display on screen.
    /// </summary>
    public class DebugBuffer : IComparer<DebugBuffer>, IComparable<DebugBuffer>, IEqualityComparer<DebugBuffer> {
        /// <summary>
        /// Static collection of messages to display on the screen.
        /// </summary>
        private static DebugMessageCollection messages;

        /// <summary>
        /// Unique identifier for the message.
        /// </summary>
        private string identifier;
        
        /// <summary>
        /// Message to display.
        /// </summary>
        private string message;
        
        /// <summary>
        /// Priority in the message list.
        /// </summary>
        private int priority;
        
        /// <summary>
        /// Location on the screen to display the message.
        /// </summary>
        private Position position;

        /// <summary>
        /// Initializes a new instance of the DebugBuffer class.
        /// </summary>
        /// <param name="identifier">Identifier for this debug message.</param>
        /// <param name="message">Message to display.</param>
        /// <param name="priority">Priority to set the message to.</param>
        /// <param name="position">Position on the screen to display message.</param>
        public DebugBuffer(string identifier, string message, int priority, Position position) {
            this.identifier = identifier;
            this.message = message;
            this.priority = priority;
            this.position = position;
        }

        /// <summary>
        /// Initializes a new instance of the DebugBuffer class.
        /// </summary>
        public DebugBuffer() {
        }

        /// <summary>
        /// Initializes a new instance of the DebugBuffer class.
        /// </summary>
        /// <param name="identifier">Identifier for this debug message.</param>
        public DebugBuffer(string identifier) {
            this.identifier = identifier;
        }

        /// <summary>
        /// Gets the debug message buffer that is displayed on the screen.
        /// </summary>
        /// <value>
        /// The debug message buffer that is displayed on the screen.
        /// </value>
        public static DebugMessageCollection Messages {
            get {
                if (messages == null) {
                    messages = new DebugMessageCollection();
                }
                
                return messages;
            }
        }

        /// <summary>
        /// Gets or sets the identifier for the debug message.
        /// </summary>
        /// <value>
        /// The identifier for the debug message.
        /// </value>
        public string Identifier {
            get {
                return this.identifier;
            }
            
            set {
                this.identifier = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the message for the debug message.
        /// </summary>
        /// <value>
        /// The message for the debug message.
        /// </value>
        public string Message {
            get {
                return this.message;
            }
            
            set {
                this.message = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the priority of the debug message.
        /// </summary>
        /// <value>
        /// The priority of the debug message.
        /// </value>
        public int Priority {
            get {
                return this.priority;
            }
            
            set {
                this.priority = value;
            }
        }
        
        /// <summary>
        /// Gets or sets the location on screen for the debug message.
        /// </summary>
        /// <value>
        /// The location on screen for the debug message.
        /// </value>
        public Position Location {
            get {
                return this.position;
            }
            
            set {
                this.position = value;
            }
        }

        /// <summary>
        /// Compares two objects to determine if they're the same.
        /// </summary>
        /// <param name="first">First object to compare.</param>
        /// <param name="second">Second object to compare.</param>
        /// <returns>True if the two objects are the same.</returns>
        public static bool operator ==(DebugBuffer first, DebugBuffer second) {
            return first.Equals(second);
        }

        /// <summary>
        /// Compares two objects to determine if they're not the same.
        /// </summary>
        /// <param name="first">First object to compare.</param>
        /// <param name="second">Second object to compare.</param>
        /// <returns>True if the two objects are not the same.</returns>
        public static bool operator !=(DebugBuffer first, DebugBuffer second) {
            return !(first == second);
        }

        /// <summary>
        /// Compares two objects to determine if the first one is less than the second.
        /// </summary>
        /// <param name="first">First object to compare.</param>
        /// <param name="second">Second object to compare.</param>
        /// <returns>True if the first object is less than the second one.</returns>
        public static bool operator <(DebugBuffer first, DebugBuffer second) {
            return first.CompareTo(second) < 0;
        }

        /// <summary>
        /// Compares two objects to determine if the first one is greater than the second.
        /// </summary>
        /// <param name="first">First object to compare.</param>
        /// <param name="second">Second object to compare.</param>
        /// <returns>True if the first object is greater than the second one.</returns>
        public static bool operator >(DebugBuffer first, DebugBuffer second) {
            return first.CompareTo(second) > 0;
        }

        /// <summary>
        /// Compares another DebugBuffer object to this instance.
        /// </summary>
        /// <param name="other">The other TileImages object to compare to.</param>
        /// <returns>Less then zero if the first item is less than the second, zero if they are the same, and greater
        /// than zero if the first is greater than the second.</returns>
        public int CompareTo(DebugBuffer other) {
            return this.priority.CompareTo(other.Priority);
        }

        /// <summary>
        /// Compare two TileImages objects to determine if they are the same.
        /// </summary>
        /// <param name="x">First object to compare.</param>
        /// <param name="y">Second object to compare.</param>
        /// <returns>Less then zero if the first item is less than the second, zero if they are the same, and greater
        /// than zero if the first is greater than the second.</returns>
        public int Compare(DebugBuffer x, DebugBuffer y) {
            return x.CompareTo(y);
        }

        /// <summary>
        /// Compares another object to this instance to determine if they're the same. Overridden.
        /// </summary>
        /// <param name="obj">Object to compare to.</param>
        /// <returns>True if the objects are the same.</returns>
        public override bool Equals(object obj) {
            if (!(obj is DebugBuffer)) {
                return false;
            }

            return this.CompareTo(obj) == 0;
        }

        /// <summary>
        /// Compares another object to this instance.
        /// </summary>
        /// <param name="other">The other object to compare to.</param>
        /// <returns>True if the two objects are the same.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "other is checked before casting.")]
        public int CompareTo(object other) {
            if (!(other is DebugBuffer)) {
                throw new ArgumentException(
                    "A DebugBuffer object is required for comparison.");
            }

            return this.CompareTo((DebugBuffer)other);
        }

        /// <summary>
        /// Generates a unique hash code for this instance.
        /// </summary>
        /// <returns>A unique hash code.</returns>
        public override int GetHashCode() {
            return this.Identifier.ToCharArray().GetHashCode();
        }

        /// <summary>
        /// Compares another object to this instance to determine if they're the same. Overridden.
        /// </summary>
        /// <param name="x">First object to compare.</param>
        /// <param name="y">Second object to compare.</param>
        /// <returns>True if the objects are the same.</returns>
        public bool Equals(DebugBuffer x, DebugBuffer y) {
            return x.Equals(y);
        }

        /// <summary>
        /// Generates a unique hash code for this instance.
        /// </summary>
        /// <param name="obj">Object to generate code for.</param>
        /// <returns>A unique hash code.</returns>
        public int GetHashCode(DebugBuffer obj) {
            return obj.GetHashCode();
        }
    }
}
